﻿using ACMESharp.Crypto;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace Service
{
    public static class RsaToolExtensions
    {
        public static RSA GenerateAlgorithm(this RsaTool tool, int keyBitLength)
        {
            return RSA.Create(keyBitLength);
        }

        public static string GenerateKeys(this RsaTool tool, int keyBitLength)
        {
            var rsa = GenerateAlgorithm(tool, keyBitLength);
            return tool.GenerateKeys(rsa);
        }

        /// <summary>
        /// Returns a DER-encoded PKCS#10 Certificate Signing Request for the given RSA parametes
        /// and the given hash algorithm.
        /// </summary>
        public static byte[] GenerateCsr(this RsaTool tool, IEnumerable<string> dnsNames, RSA rsa, HashAlgorithmName? hashAlgor = null)
        {
            if (hashAlgor == null)
                hashAlgor = HashAlgorithmName.SHA256;

            string firstName = null;
            var sanBuilder = new SubjectAlternativeNameBuilder();
            foreach (var n in dnsNames)
            {
                sanBuilder.AddDnsName(n);
                if (firstName == null)
                    firstName = n;
            }
            if (firstName == null)
                throw new ArgumentException("Must specify at least one name");
            var dn = new X500DistinguishedName($"CN={firstName}");
            var csr = new CertificateRequest(dn,
                    rsa, hashAlgor.Value, RSASignaturePadding.Pkcs1);
            csr.CertificateExtensions.Add(sanBuilder.Build());
            return csr.CreateSigningRequest();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="tool"></param>
        /// <param name="dnsNames">dnsName</param>
        /// <param name="rsa">rsa</param>
        /// <param name="cn">颁发给xx</param>
        /// <param name="o">组织</param>
        /// <param name="ou">组织单位</param>
        /// <param name="l">城市</param>
        /// <param name="st">省份</param>
        /// <param name="c">国家</param>
        /// <param name="hashAlgor"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static byte[] GenerateCsr(this RsaTool tool, IEnumerable<string> dnsNames, RSA rsa,string cn,string o,string ou,string l,string st,string c ,HashAlgorithmName? hashAlgor = null)
        {
            if (hashAlgor == null)
                hashAlgor = HashAlgorithmName.SHA256;

            string firstName = null;
            var sanBuilder = new SubjectAlternativeNameBuilder();
            foreach (var n in dnsNames)
            {
                sanBuilder.AddDnsName(n);
                if (firstName == null)
                    firstName = n;
            }
            if (firstName == null)
                throw new ArgumentException("Must specify at least one name");
            List<string> info = new List<string>();
            if (!string.IsNullOrEmpty(cn))
            {
                info.Add($"CN={cn}");
            }
            else
            {
                info.Add($"CN={firstName}");
            }
            if (!string.IsNullOrEmpty(o)) info.Add($"O={o}");
            if (!string.IsNullOrEmpty(ou)) info.Add($"OU={ou}");
            if (!string.IsNullOrEmpty(l)) info.Add($"L={l}");
            if (!string.IsNullOrEmpty(st)) info.Add($"ST={st}");
            if (!string.IsNullOrEmpty(c)) info.Add($"C={c}");
            var dn = new X500DistinguishedName(string.Join(",", info));
            var csr = new CertificateRequest(dn,
                    rsa, hashAlgor.Value, RSASignaturePadding.Pkcs1);
            csr.CertificateExtensions.Add(sanBuilder.Build());
            return csr.CreateSigningRequest();
        }
    }
}
